package Gr

import (
	"database/sql"
	"fmt"
	"github.com/xwb1989/sqlparser"
	"db2s/ETL"
	"runtime"
	"strings"
)

type SqlParse struct {
	Sql string `json:"sql"`
}
type Analyze struct {
	LogSeq    int64
	Sql       string `json:"sql"`
	TableName string `json:"tableName"`
}

func (cs SqlParse) TableNameParse() (any, error) {
	var (
		tableNames = make([]string, 0)
		stmt       sqlparser.Statement
		err        error
	)
	if stmt, err = sqlparser.Parse(cs.Sql); err != nil {
		return nil, err
	}
	_ = sqlparser.Walk(func(node sqlparser.SQLNode) (kongTiNue bool, err error) {
		switch node1 := node.(type) {
		case *sqlparser.AliasedTableExpr:
			if tableNameExpr, ok := node1.Expr.(sqlparser.TableName); ok {
				if len(tableNameExpr.Name.CompliantName()) > 0 {
					if len(node1.As.String()) > 0 {
						if len(tableNameExpr.Qualifier.String()) > 0 {
							tableNames = append(tableNames, fmt.Sprintf("%v.%v", tableNameExpr.Qualifier, tableNameExpr.Name.CompliantName()))
						} else {
							tableNames = append(tableNames, tableNameExpr.Name.CompliantName())
						}
					} else {
						if len(tableNameExpr.Qualifier.String()) > 0 {
							tableNames = append(tableNames, fmt.Sprintf("%v.%v", tableNameExpr.Qualifier, tableNameExpr.Name.CompliantName()))
						} else {
							tableNames = append(tableNames, tableNameExpr.Name.CompliantName())
						}
					}
				}

			}
		}
		return true, nil
	}, stmt)
	return tableNames, nil
}

// TableStruct 获取表结构
func (cs Analyze) TableStruct(db *sql.DB) (any, error) {
	var (
		entry any
		err   error
	)
	structSql := fmt.Sprintf("show create table %v", cs.TableName)
	active := ETL.InstanceActiveS{DB: db}
	if _, entry, err = active.SqlQuery(structSql, ETL.String); err != nil {
		return nil, err
	}
	return entry, nil
}
func (cs Analyze) TableDistributed(db *sql.DB) (any, error) {
	var (
		event       = "[TableDistribution]"
		execTimeout int64
		schemaJoin  string
		tableJoin   string
		err         error
		f1          any
	)
	pc, _, _, _ := runtime.Caller(1)
	callingFunc := runtime.FuncForPC(pc)
	callFile, callLine := callingFunc.FileLine(pc)
	callFunc := callingFunc.Name()
	callFuncInfo := fmt.Sprintf("Call functions %v Call File %v:%v", callFunc, callFile, callLine)
	vlog = fmt.Sprintf("(%d) %v %v Start querying the distribution of table %v", cs.LogSeq, callFuncInfo, event, cs.TableName)
	WLog.Debug(vlog)
	if strings.Contains(cs.TableName, ".") {
		l := strings.Split(cs.TableName, ".")
		schemaJoin = l[0]
		tableJoin = l[1]
	}
	strSql := fmt.Sprintf("select concat(`SCHEMA_NAME`,'.',`TABLE_NAME`) as `tableName`,`DISTRIBUTE_MODE` as `shardMode`,`SHARD_NAME` as `ShardName`,`PARTITION_ID` as `partitionId` from `information_schema`.`GREATDB_TABLE_DISTRIBUTION` where SCHEMA_NAME in ('%v') and TABLE_NAME in ('%v')", schemaJoin, tableJoin)
	active := ETL.InstanceActiveS{DBType: DBType, DB: db}
	if execTimeout, f1, err = active.SqlQuery(strSql, ETL.SMap); err != nil {
		vlog = fmt.Sprintf("(%d) %v %v The execution of a sql statement failed. sql is {%v},error is {%v}", cs.LogSeq, callFuncInfo, event, strSql, err)
		WLog.Error(vlog)
		return nil, err
	}
	vlog = fmt.Sprintf("(%d) %v %v A sql statement was executed successfully. sql is {%v}, exec timeout is {%vms}", cs.LogSeq, callFuncInfo, event, strSql, execTimeout)
	WLog.Debug(vlog)
	vlog = fmt.Sprintf("(%d) %v %v The distribution query of table %v.%v is completed. result is {%v}", cs.LogSeq, callFuncInfo, event, schemaJoin, tableJoin, f1)
	WLog.Debug(vlog)
	return f1, nil
}

// TableIndex 获取表索引信息
func (cs Analyze) TableIndex(db *sql.DB) (any, error) {
	var (
		entry any
		err   error
	)
	structSql := fmt.Sprintf("show index from %v", cs.TableName)
	active := ETL.InstanceActiveS{DB: db}
	if _, entry, err = active.SqlQuery(structSql, ETL.String); err != nil {
		return nil, err
	}
	return entry, nil
}
func (cs SqlParse) TableNameParse1(stmt sqlparser.Statement) any {
	var (
		tableNames = make([]string, 0)
	)
	_ = sqlparser.Walk(func(node sqlparser.SQLNode) (kongTiNue bool, err error) {
		switch node1 := node.(type) {
		case *sqlparser.AliasedTableExpr:
			if tableNameExpr, ok := node1.Expr.(sqlparser.TableName); ok {
				if len(tableNameExpr.Name.CompliantName()) > 0 {
					if len(node1.As.String()) > 0 {
						if len(tableNameExpr.Qualifier.String()) > 0 {
							tableNames = append(tableNames, fmt.Sprintf("%v.%v", tableNameExpr.Qualifier, tableNameExpr.Name.CompliantName()))
						} else {
							tableNames = append(tableNames, tableNameExpr.Name.CompliantName())
						}
					} else {
						if len(tableNameExpr.Qualifier.String()) > 0 {
							tableNames = append(tableNames, fmt.Sprintf("%v.%v", tableNameExpr.Qualifier, tableNameExpr.Name.CompliantName()))
						} else {
							tableNames = append(tableNames, tableNameExpr.Name.CompliantName())
						}
					}
				}

			}
		}
		return true, nil
	}, stmt)
	return tableNames
}
func (cs SqlParse) Parse() any {
	//cs.Sql = "SELECT * FROM users WHERE id = 1 UNION SELECT * FROM products WHERE price > 100"
	//cs.Sql = "select p.id,p.name,p1.code,p1.class from t2 p left join t1 p1 on p.id = p1.id where p.id >=1 and p.id <=5"
	//cs.Sql = "select c.id from pcms.yu1 as c inner join (select p.id,p.name,p1.code,p1.class from t2 p left join t1 p1 on p.id = p1.id where p.id >=1 and p.id <=5) d on c.id = d.id where c.id = 1"
	//cs.Sql = "SELECT id, name FROM users WHERE id = 1"
	//fmt.Println("---------pppppp:", cs.Sql)

	//select into 不支持
	cs.Sql = "select * from bboss_prov.prov_work_order partition (p4) into outfile '/greatdb/exportdata/prov_work_order_p4.csv' FIELDS TERMINATED BY '|+|'  ESCAPED BY '' LINE\nSs TERMINATED BY '/*rowsxxx*/'"
	//
	//cs.Sql = "SELECT distinct a.ORDERNUMBER,a.ACTIVITYNAME\nFROM\n        bboss_bpm.bpm_instance_task a\n        LEFT JOIN bboss_bpm.bpm_procdef_nodemap b ON SUBSTRING_INDEX( a.ROLE_NAME, ':',- 2 )= SUBSTRING_INDEX( b.ROLE_NAME, ':',- 2 )\nWHERE\n        b.ROLE_NAME LIKE '%provision%'\n        and a.ACTIVITYNAME not in('网络部施工并反馈','网络部办理','网络部开通办理','网络部办理变更开通','网络部办理注销')\n        and a.TASK_COMPTIME >= DATE_SUB(NOW(),INTERVAL 7 DAY)\n        and a.TASK_COMPTIME   <         DATE_SUB(now(), interval 10 minute)\n        AND NOT EXISTS (        SELECT 1 FROM bboss_prov.prov_work_order f\n        WHERE   f.product_ordernumber = a.ORDERNUMBER\n        and a.task_id=SUBSTRING_INDEX(f.task_id,'/',-1)\n        and  f.CREATE_TIME >= DATE_SUB(NOW(),INTERVAL 7 DAY)\n        and f.CREATE_TIME <= DATE_SUB(now(), interval 10 minute));"
	cs.Sql = "select * from ( select tmp_page.*, rownum row_id from ( select t.inst_id,\n                       t.inst_crtime,\n                       t.inst_comptime,\n                       t.procdef_id,\n                       t.inst_name,\n                       t.ordernumber,\n                       t.businesscode,\n                       t.inst_state,\n                       t.sourcedata\n                 from bpm_procinstance t\n                 where  1=1\n                     and t.inst_name like concat('%','虚拟','%')\n                 order by t.inst_crtime desc ) tmp_page where rownum <= 12 ) where row_id > 0;"
	if stmt, err := sqlparser.Parse(cs.Sql); err != nil {
		fmt.Println("----error:", err)
		return nil
	} else {
		fmt.Println("-------000000")
		fmt.Println("---------fff:", cs.TableNameParse1(stmt))
		//switch stmt1 := stmt.(type) {
		//case *sqlparser.Select:
		//for _, table := range stmt1.From {
		//switch tableExpr := table.(type) {
		//case *sqlparser.AliasedTableExpr:
		//if tableName, ok := tableExpr.Expr.(sqlparser.TableName); ok {
		//	fmt.Println("Table name:", tableName.Name.String())
		//}
		//case *sqlparser.JoinTableExpr:
		//if tableName, ok := tableExpr.LeftExpr.(*sqlparser.AliasedTableExpr).Expr.(sqlparser.TableName); ok {
		//	fmt.Println("Table name:", tableName.Name.String())
		//}
		//if tableName, ok := tableExpr.RightExpr.(*sqlparser.AliasedTableExpr).Expr.(sqlparser.TableName); ok {
		//	fmt.Println("Table name:", tableName.Name.String())
		//}
		//}
		//}
		//case *sqlparser.Union:
		//for _, table := range stmt1.From {
		//	switch tableExpr := table.(type) {
		//	case *sqlparser.AliasedTableExpr:
		//		//table1 := table.(type)
		//		if tableName, ok := tableExpr.Expr.(sqlparser.TableName); ok {
		//			fmt.Println("Table name:", tableName.Name.String())
		//		}
		//	}
		//}
		//default:
		//fmt.Printf("Unknown statement type: %T\n", stmt)
		//}
	}
	return nil
}
